#include "ASTNode.h"
#include <iostream>
#include <iomanip>

// 获取节点类型名称
std::string ASTNode::getNodeTypeName() const {
    switch (nodeType) {
        case NodeType::PROGRAM: return "Program";
        case NodeType::COMP_UNIT: return "CompUnit";
        case NodeType::CONST_DECL: return "ConstDecl";
        case NodeType::VAR_DECL: return "VarDecl";
        case NodeType::CONST_DEF: return "ConstDef";
        case NodeType::VAR_DEF: return "VarDef";
        case NodeType::FUNC_DEF: return "FuncDef";
        case NodeType::FUNC_FPARAM: return "FuncFParam";
        case NodeType::FUNC_FPARAMS: return "FuncFParams";
        case NodeType::FUNC_RPARAM: return "FuncRParam";
        case NodeType::FUNC_RPARAMS: return "FuncRParams";
        case NodeType::BLOCK: return "Block";
        case NodeType::ASSIGN_STMT: return "AssignStmt";
        case NodeType::EXPR_STMT: return "ExprStmt";
        case NodeType::RETURN_STMT: return "ReturnStmt";
        case NodeType::IF_STMT: return "IfStmt";
        case NodeType::BINARY_EXPR: return "BinaryExpr";
        case NodeType::UNARY_EXPR: return "UnaryExpr";
        case NodeType::CALL_EXPR: return "CallExpr";
        case NodeType::IDENT_EXPR: return "IdentExpr";
        case NodeType::LITERAL_EXPR: return "LiteralExpr";
        case NodeType::PAREN_EXPR: return "ParenExpr";
        case NodeType::BASIC_TYPE: return "BasicType";
        case NodeType::INIT_VAL: return "InitVal";
        case NodeType::CONST_INIT_VAL: return "ConstInitVal";
        default: return "Unknown";
    }
}

// 打印AST树
void ASTNode::printTree(int depth) const {
    // 打印缩进
    for (int i = 0; i < depth; ++i) {
        std::cout << "  ";
    }
    
    // 打印节点类型
    std::cout << getNodeTypeName();
    
    // 对于具体节点类型，打印额外信息
    switch (nodeType) {
        case NodeType::BASIC_TYPE: {
            const BasicTypeNode* typeNode = static_cast<const BasicTypeNode*>(this);
            std::cout << " (" << typeNode->typeName << ")";
            break;
        }
        case NodeType::IDENT_EXPR: {
            const IdentExprNode* identNode = static_cast<const IdentExprNode*>(this);
            std::cout << " (" << identNode->identifier << ")";
            break;
        }
        case NodeType::LITERAL_EXPR: {
            const LiteralExprNode* literalNode = static_cast<const LiteralExprNode*>(this);
            std::cout << " (" << literalNode->literalType << ": " << literalNode->value << ")";
            break;
        }
        case NodeType::BINARY_EXPR: {
            const BinaryExprNode* binaryNode = static_cast<const BinaryExprNode*>(this);
            std::cout << " (" << binaryNode->op << ")";
            break;
        }
        case NodeType::UNARY_EXPR: {
            const UnaryExprNode* unaryNode = static_cast<const UnaryExprNode*>(this);
            std::cout << " (" << unaryNode->op << ")";
            break;
        }
        case NodeType::FUNC_DEF: {
            const FuncDefNode* funcNode = static_cast<const FuncDefNode*>(this);
            std::cout << " (" << funcNode->identifier << ")";
            break;
        }
        case NodeType::CALL_EXPR: {
            const CallExprNode* callNode = static_cast<const CallExprNode*>(this);
            std::cout << " (" << callNode->funcName << ")";
            break;
        }
        case NodeType::CONST_DEF: {
            const ConstDefNode* constNode = static_cast<const ConstDefNode*>(this);
            std::cout << " (" << constNode->identifier << ")";
            break;
        }
        case NodeType::VAR_DEF: {
            const VarDefNode* varNode = static_cast<const VarDefNode*>(this);
            std::cout << " (" << varNode->identifier << ")";
            break;
        }
        case NodeType::FUNC_FPARAM: {
            const FuncFParamNode* paramNode = static_cast<const FuncFParamNode*>(this);
            std::cout << " (" << paramNode->identifier << ")";
            break;
        }
        default:
            break;
    }
    
    std::cout << std::endl;
    
    // 递归打印子节点和特定字段
    switch (nodeType) {
        case NodeType::FUNC_DEF: {
            const FuncDefNode* funcNode = static_cast<const FuncDefNode*>(this);
            if (funcNode->returnType) funcNode->returnType->printTree(depth + 1);
            if (funcNode->params) funcNode->params->printTree(depth + 1);
            if (funcNode->body) funcNode->body->printTree(depth + 1);
            break;
        }
        case NodeType::BINARY_EXPR: {
            const BinaryExprNode* binaryNode = static_cast<const BinaryExprNode*>(this);
            if (binaryNode->left) binaryNode->left->printTree(depth + 1);
            if (binaryNode->right) binaryNode->right->printTree(depth + 1);
            break;
        }
        case NodeType::UNARY_EXPR: {
            const UnaryExprNode* unaryNode = static_cast<const UnaryExprNode*>(this);
            if (unaryNode->operand) unaryNode->operand->printTree(depth + 1);
            break;
        }
        case NodeType::RETURN_STMT: {
            const ReturnStmtNode* returnNode = static_cast<const ReturnStmtNode*>(this);
            if (returnNode->expr) returnNode->expr->printTree(depth + 1);
            break;
        }
        case NodeType::VAR_DECL: {
            const VarDeclNode* varDeclNode = static_cast<const VarDeclNode*>(this);
            if (varDeclNode->bType) varDeclNode->bType->printTree(depth + 1);
            break;
        }
        case NodeType::VAR_DEF: {
            const VarDefNode* varDefNode = static_cast<const VarDefNode*>(this);
            if (varDefNode->initVal) varDefNode->initVal->printTree(depth + 1);
            break;
        }
        case NodeType::INIT_VAL: {
            const InitValNode* initValNode = static_cast<const InitValNode*>(this);
            if (initValNode->expr) initValNode->expr->printTree(depth + 1);
            break;
        }
        default:
            // 对于其他节点类型，打印children
            for (const auto& child : children) {
                if (child) {
                    child->printTree(depth + 1);
                }
            }
            break;
    }
}

// 各种节点的accept方法实现
void ProgramNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void CompUnitNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void BasicTypeNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void ConstDeclNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void VarDeclNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void ConstDefNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void VarDefNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void FuncDefNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void FuncFParamNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void BlockNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void AssignStmtNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void ExprStmtNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void ReturnStmtNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void IfStmtNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void BinaryExprNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void UnaryExprNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void CallExprNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void IdentExprNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void LiteralExprNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void ParenExprNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void InitValNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

void ConstInitValNode::accept(ASTVisitor& visitor) {
    visitor.visit(*this);
}

